/**
 * Created by seth.yang on 2016/10/12
 */
if (!window.ImageBrowser) var ImageBrowser = (function ($) {
    var MAX_SIZE = 100, MAX_HEIGHT = 46;
    var settings, root, table, mask, title, locationBar, browser, folderName, sample, info,
        uploadPanel, createFolderPanel, imageItems, data = [], myDoc, pubDoc,
        selectedImageItem, maskSet = false, loading, theForm,
        defaults = {
            method:'GET',
            'list-service':'uploader/image-list',
            'upload-service':'uploader/uploader',
            'create-folder':'uploader/create-folder'
        }, config = (function () {
            var defaults = {'public':'公共图片', 'private':'我的图片'};
            return {
                push : function (key, value) {
                    defaults [key] = value;
                },
                contains : function (key) {
                    return key in defaults;
                },
                getLabel : function (key) {
                    return defaults [key];
                },
                remove : function (key) {
                    if (key in defaults)
                        delete  defaults [key];
                },
                retain : function () {
                    var a = [];
                    for (var i = 0; i < arguments.length; i ++) {
                        var value = arguments [i];
                        if (typeof value === 'string') a.push (value);
                        else if (value instanceof Array) a = a.concat (value);
                    }

                    for (i = 0; i < a.length; i ++) {
                        if (!(a[i] in defaults)) delete defaults [a [i]];
                    }
                },
                clear : function () {
                    defaults = {'public':'公共图片', 'private':'我的图片'};
                },
                acceptTypes : /\.(jpg|jpeg|png|gif|zip|rar)$/i
            };
        })();
    var tableTemplate =
        "<table id=\"browser-root\" class=\"browser-root\" cellpadding=\"0\" cellspacing=\"0\" style=\"position:fixed\">\n" +
        "    <tr valign=\"top\">\n" +
        "        <td class=\"browser-left\">\n" +
        "            <ul>\n" +
        "                <li><a id=\"browser-my-images\" class=\"browser-nav-item-selected\" data-folder-name=\"private\">我的图片</a></li>\n" +
        "                <li><a id=\"browser-public-images\" class=\"browser-nav-item\" data-folder-name=\"public\">公共图片</a></li>\n" +
        "            </ul>\n" +
        "        </td>\n" +
        "        <td class=\"browser-right\">\n" +
        "            <div class=\"browser-top\">\n" +
        "                <div class=\"browser-operation-panel\">\n" +
        "                    <a data-dialog-name=\"browser-create-folder\" class=\"browser-button\">新建目录</a>\n" +
        "                    <a data-dialog-name=\"browser-upload-panel\" class=\"browser-button\">上传图片</a>\n" +
        "                </div>\n" +
        "                <div class=\"browser-title-panel\">\n" +
        "                    <h1 id=\"browser-folder-name\">图片库</h1>\n" +
        "                    <div id=\"browser-location-bar\"></div>\n" +
        "                </div>\n" +
        "                <div class=\"clear\"></div>\n" +
        "            </div>\n" +
        "            <div id=\"browser-main\" class=\"browser-main\">\n" +
        "            </div>\n" +
        "        </td>\n" +
        "    </tr>\n" +
        "    <tr>\n" +
        "        <td colspan=\"2\">\n" +
        "            <div class=\"browser-bottom\">\n" +
        "                <div id=\"browser-info-panel\">\n" +
        "                    <div id=\"browser-image-sample\"></div>\n" +
        "                    <div id=\"browser-info\"></div>\n" +
        "                </div>\n" +
        "                <div class=\"browser-operation-panel\">\n" +
        "                    <a id=\"browser-select-image\" class=\"browser-button\">确定</a>\n" +
        "                    <a id=\"browser-btn-cancel\" class=\"browser-button\">取消</a>\n" +
        "                </div>\n" +
        "                <div class=\"clear\"></div>\n" +
        "            </div>\n" +
        "        </td>\n" +
        "    </tr>\n" +
        "</table>" +
        "<iframe id=\"browser-upload-frame\" name=\"browser-upload-frame\" style=\"display:none\"></iframe>";
    var uploadDialogTemplate =
        "<div id=\"browser-upload-panel\" class=\"browser-dialog-panel\">\n" +
        "    <form enctype=\"multipart/form-data\" method=\"post\" id=\"uploadForm\" target=\"browser-upload-frame\">\n" +
        "        <input type=\"hidden\" id=\"browser-folderName\" name=\"folderName\" value='private'/>\n" +
        "        <div style=\"margin-bottom:10px;\">请选择图片: <input type=\"file\" name=\"file\" id=\"browser-file\"/></div>\n" +
        "        <div class=\"browser-detail\">支持的图片类型为：\n" +
        "            <span class=\"browser-high-light\">GIF</span>,\n" +
        "            <span class=\"browser-high-light\">JPEG</span>,\n" +
        "            <span class=\"browser-high-light\">PNG</span>\n" +
        "        </div>\n" +
        "        <div class=\"browser-operation-panel\">\n" +
        "            <a id='browser-button-upload' class=\"browser-button\">上传</a>\n" +
        "            <a data-dialog-name='browser-upload-panel' data-action='close' class=\"browser-button\">取消</a>\n" +
        "            <div class=\"clear\"></div>\n" +
        "        </div>\n" +
        "    </form>\n" +
        "</div>\n";
    var createFolderTemplate =
        "<div id=\"browser-create-folder\" class=\"browser-dialog-panel\">\n" +
        "    <div>\n" +
        "        <label for=\"browser-txt-folder-name\">请输入目录名称</label>:\n" +
        "        <input type=\"text\" id=\"browser-txt-folder-name\" style=\"width: 100%\"/>\n" +
        "    </div>\n" +
        "    <div class=\"browser-detail\">目录名称不能包含\n" +
        "        <span class=\"browser-high-light\">/</span>,\n" +
        "        <span class=\"browser-high-light\">\\</span>,\n" +
        "        <span class=\"browser-high-light\">?</span>,\n" +
        "        <span class=\"browser-high-light\">*</span> 和\n" +
        "        <span class=\"browser-high-light\">空格</span>\n" +
        "    </div>\n" +
        "    <div class=\"browser-operation-panel\">\n" +
        "        <a id=\"browser-btn-create\" class=\"browser-button\">确定</a>\n" +
        "        <a data-dialog-name=\"browser-create-folder\" data-action='close' class=\"browser-button\">取消</a>\n" +
        "        <div class=\"clear\"></div>\n" +
        "    </div>\n" +
        "</div>\n";
    var loadingTemplate =
        "<table style='width:100%;min-height:100%'><tr><td class='browser-loading-cell'></td></tr></table>";
    function buildPath (a, i) {
        var s = '';
        for (var j = 0; j <= i; j ++) {
            if (s.length > 0) s += '/';
            s += a[j];
        }
        return s;
    }

    function buildPathLabel (path) {
        if (!path || path.replace (/^\s+|\s+$/ig, '') == 0)
            return path;
        if (path.charAt(0) == '/')
            path = path.substring (1);

        var a = path.split ('/');
        var s = a [0];
        for (var i = 1; i < a.length; i ++) {
            var part = a [i];
            if (config.contains (part))
                part = config.getLabel (part);
            s += '/' + part;
        }

        return s;
    }

    function showImageInfo (item) {
        if (!item) {
            sample.empty ();
            info.empty ();
            return;
        }
        var html = '<img src="' + item.src + '" style="border:1px solid #ccc;';
        var w = item.width, h = item.height;
        if (h > MAX_HEIGHT) {
            var scale = MAX_HEIGHT / h;
            html += 'width:' + parseInt (w * scale, 10) + 'px;height:' + parseInt (h * scale, 10) + 'px';
        }
        html += '"/>';
        sample.html (html);

        html = "<div class='browser-file-name'>" + item.name + '</div>';
        html += "<div class='browser-detail'>" + item.type + '图像 &nbsp; 尺寸: ' + item.width + ' x ' +
            item.height + ' &nbsp; 最后修改时间：' + item['lastModify'] + '</div>';
        info.html (html);
    }

    function fetchData (folder) {
        var dir;
        if (typeof folder == 'string') {
            dir = folder;
        } else {
            dir = folderName.val ();
        }

        if (selectedImageItem) {
            selectedImageItem = null;
            showImageInfo (null);
        }
        loading.appendTo (browser.empty ()).show ();
        $.ajax ({
            url:settings ['list-service'],
            type:settings['method'],
            data: {
                a:'image-list',
                path: dir
            }
        }).success (function (response) {
            data = eval ('(' + response + ')');
            loading.appendTo (root).hide ();
            if (data && data.length) {
                config.retain(dir.split('/'));
                loadImages();
            }
        }).error (function (e, response) {
            console.error (e);
            console.error (response);
            loading.appendTo (root).hide ();
        });
    }

    function onItemClicked () {
        var expr = $(this).attr ('data-json-expr');
        var item = eval ('(' + expr + ')');
        if (item) {
            if (item.type == 'folder') {
                var name = folderName.val () + '/' + item.src;
                changeFolder (name);
            } else {
                if (selectedImageItem) {
                    selectedImageItem.removeClass ('browser-image-item-selected').addClass ('browser-image-item');
                }
                selectedImageItem = $(this);
                selectedImageItem.removeClass ('browser-image-item').addClass ('browser-image-item-selected');
                showImageInfo(item);
            }
        }
    }

    function changeFolder (name) {
        var folder;
        if (typeof name == 'string') {
            folder = name;
        } else {
            folder = $(this).attr ('data-folder-name');
        }
        var a = folder.split ('/');
        if (a [0] == 'private') {
            myDoc.removeClass ('browser-nav-item').addClass ('browser-nav-item-selected');
            pubDoc.removeClass ('browser-nav-item-selected').addClass ('browser-nav-item');
        } else {
            myDoc.removeClass ('browser-nav-item-selected').addClass ('browser-nav-item');
            pubDoc.removeClass ('browser-nav-item').addClass ('browser-nav-item-selected');
        }

        if (folderName.val () != folder) {
            fetchData (folder);
            folderName.val (folder);
        }

        locationBar.empty ();
        var ul = $('<ul class="browser-location"/>').appendTo (locationBar);
        for (var i = 0; i < a.length; i ++) {
            var path = a[i];
            if (path == '') continue;

            if (i != 0) {
                var separator = $('<li class="browser-separator"/>').appendTo (ul);
            }

            var label = (config.contains(path)) ? config.getLabel (path) : path;
            var li = $('<li />').appendTo (ul);
            $('<a/>').attr ('data-folder-name', buildPath(a, i)).text (label).on ('click', changeFolder).appendTo (li);
        }
    }

    function openDialog () {
        var self = $(this),
            name = self.attr ('data-dialog-name'),
            dialog = $('#' + name);
        if (self.attr ('data-action') == 'close') {
            mask.hide ();
            dialog.hide ();
        } else {
            mask.show();
            dialog.show();
            dialog.css(center(dialog));
        }
    }

    function center (dialog) {
        var W = $(window).width (), H = $(window).height (),
            w = dialog.width (), h = dialog.height ();
        return {
            left: (W - w) / 2, top: (H - h) / 2
        };
    }

    function selectImage () {
        if (selectedImageItem) {
            if (('onselected' in settings) && typeof settings['onselected'] == 'function') {
                var expr = selectedImageItem.attr ('data-json-expr');
                var item = eval ('(' + expr + ')');
                console.info (item);
                settings ['onselected'] (item);
            }
            cancel ();
        } else {
            alert ('please select an image.');
        }
    }

    function cancel () {
        root.hide ();
    }

    function createFolder () {
        var currentFolder = folderName.val ();
        var path = document.getElementById ('browser-txt-folder-name').value;
        if (path == '' || path.replace(/^\s+|\s+$/g, '').length == 0) {
            alert ('请输入要创建的目录名称');
            return;
        }

        if (/[\\\/\*\?\s]/ig.test (path)) {
            alert ('无效的目录名称');
            return;
        }
        var name = buildPathLabel (currentFolder + '/' + path);
        $.ajax ({
            url:settings['create-folder'],
            type:'POST',
            data:{a:'create-folder', folderName:name}
        }).success (function (response) {
            var ret = eval ('(' + response + ')');
            if (ret.status == 'ok') {
                setTimeout (function () {
                    var dataItem = {name:path, type:'folder',src:ret.src};
                    config.push (ret.src, path);
                    var a = createItem (dataItem);
                    var div = document.getElementById ('browser-main');
                    div.insertBefore (a[0], div.firstChild);
                }, 0);
                mask.hide ();
                createFolderPanel.hide ();
            } else {
                alert (result ['cause']);
            }
        }).error ();
    }

    function loadImages () {
        browser.empty ();
        imageItems = [];
        for (var i = 0; i < data.length; i ++) {
            var dataItem = data [i];
            config.push (dataItem.src, dataItem.name);
            createItem (dataItem).appendTo (browser);
            //container.appendChild (createItem (dataItem));
        }
    }

    function createItem (dataItem) {
        var a = $('<a class="browser-image-item"/>')
            .attr ('data-json-expr', Reflector.toJsonString (dataItem)).on ('click', onItemClicked);
        var div = $('<div class="browser-image-holder"/>').appendTo (a);
        div = $('<div class="browser-img-border"/>').appendTo (div);
        var img = $('<img/>').attr ({
            src: dataItem.type == 'folder' ? 'browser/resource/images/folder.png' : dataItem.src
        }).appendTo (div);
        if (dataItem.width > MAX_SIZE || dataItem.height > MAX_SIZE) {
            var n = Math.max (dataItem.width, dataItem.height);
            var scale = MAX_SIZE / n;
            img.css ({
                width: parseInt (dataItem.width * scale, 10),
                height: parseInt (dataItem.height * scale, 10)
            });
        }
        $('<div class="browser-txt"/>').text (dataItem.name).appendTo (a);
        return a;
    }

    function createPanel () {
        root = $('<div style="position:fixed;display:none"/>').appendTo ($(document.body));
        $('<div class="browser-mask"/>').css ({'min-height':'100%', width:'100%'}).appendTo (root);
        table = $(tableTemplate).appendTo (root);
        mask = $('<div class="browser-mask" />').appendTo (root).hide ();
        $(uploadDialogTemplate).appendTo (root);
        $(createFolderTemplate).appendTo (root);
        loading = $(loadingTemplate).appendTo (root).hide ();

        title = root.find ('#browser-folder-name');
        locationBar = root.find ('#browser-location-bar');
        browser = root.find ('#browser-main');
        sample = root.find ('#browser-image-sample');
        info = root.find ('#browser-info');
        uploadPanel = root.find ('#browser-upload-panel');
        createFolderPanel = root.find ('#browser-create-folder');
        folderName = root.find ('#browser-folderName');
        myDoc = root.find ('#browser-my-images');
        pubDoc = root.find ('browser-public-images');
        theForm = root.find ('#browser-upload-frame').on ('load', fetchData);

        root.find ('#browser-select-image').on ('click', selectImage);
        root.find ('#browser-btn-cancel').on ('click', cancel);
        root.find ('#browser-btn-create').on ('click', createFolder);
        root.find ('#browser-button-upload').on ('click', uploadFile);
        root.find ('a[data-folder-name]').on ('click', changeFolder);
        root.find ('a[data-dialog-name]').on ('click', openDialog);
    }

    function uploadFile () {
        var form = document.getElementById ('uploadForm');
        form.action = settings ['upload-service'];
        var file = document.getElementById ('browser-file');
        if (file.value == '') {
            alert ('请选择图片');
            return;
        }
        if (!config.acceptTypes.test (file.value)) {
            alert ('不支持的图片格式，请选择\r\nGIF, JPEG或PNG格式的图片');
            return;
        }

        var c = document.getElementById ('browser-folderName');
        var backup = c.value;
        c.value = buildPathLabel (backup);

        form.submit ();
        uploadPanel.hide ();
        mask.hide ();
        c.value = backup;
    }

    return {
        setup : function (options) {
            settings = $.extend ({}, defaults, options || {});
            createPanel ();
            return this;
        },
        show : function () {
            fetchData ();
            root.show ();

            var css = center (table);
            table.css (css);
            if (!maskSet) {
                mask.css({
                    left:   css.left, top: css.top,
                    width:  table.width() + 2,
                    height: table.height() + 2
                });

                maskSet = true;
            }
            return this;
        },
        hide : function () {
            root.hide ();
            return this;
        }
    };
}) (jQuery);